//////////////////////////////////////////////////////////////////////////////////
//	 Copyright 2011 by Yosef Grabivker, ryuho@homenetworksoft.com
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//////////////////////////////////////////////////////////////////////////////////

#include <wx/wx.h>
#include "advancedoptdlg.h"
#include <wx/propgrid/propgrid.h>
#include "../common/MarkupSTL.h"
#include "rcmdapp.h"
#include "mainwnd.h"


enum cIDS{ cGridCtrlID=12401, cBtnDefaultID };

//#pragma comment (lib,"wxcode_msw28ud_propgrid")


BEGIN_EVENT_TABLE(CAdvancedOptDlg, wxDialog)
	EVT_CLOSE(CAdvancedOptDlg::OnClose)
	EVT_BUTTON(cBtnDefaultID, CAdvancedOptDlg::OnDefault)
END_EVENT_TABLE()

CAdvancedOptDlg::CAdvancedOptDlg(wxWindow* pParent):
	wxDialog(pParent, wxID_ANY, _("Custom settings"), wxDefaultPosition, wxSize(440, 500),
		wxCAPTION|wxRESIZE_BORDER|wxCLOSE_BOX|wxSTAY_ON_TOP )
{
	wxBoxSizer* szMain = new wxBoxSizer(wxVERTICAL);
 
	//Have to set wxPG_EX_DISABLE_TLP_TRACKING, crashed on Linux
	m_pGrid = new wxPropertyGrid(this, cGridCtrlID,
		wxDefaultPosition, wxSize(400,400), wxPG_BOLD_MODIFIED|wxPG_AUTO_SORT|wxPG_EX_DISABLE_TLP_TRACKING);

	CreateGrid();
	
	m_pGrid->SetExtraStyle( GetExtraStyle() | wxPG_EX_DISABLE_TLP_TRACKING );

	szMain->Add(m_pGrid,1, wxALL|wxEXPAND,5);

	wxSizer* sz = CreateStdDialogButtonSizer(wxOK|wxCANCEL);

	wxButton* pDef = new wxButton(this, cBtnDefaultID, _("Default") );

	sz->Add(pDef, 0, wxLEFT, 4);

	szMain->Add(sz,0, wxALIGN_CENTER);

	SetSizer(szMain);
}

void CAdvancedOptDlg::CreateGrid()
{
	m_pGrid->Clear();

	m_pGrid->Append( new wxPropertyCategory(wxT("NAT")) );

	NATTIMEOUTS def;
	NATTIMEOUTS timeouts;
	timeouts = wxGetApp().GetMainWnd()->GetLogic().GetActualTCPTimeOuts();

	m_pGrid->Append( new wxIntProperty(wxT("ip_conntrack_generic_timeout"),			wxPG_LABEL, std::min(timeouts.stGeneric, def.stGeneric)			) );
	m_pGrid->Append( new wxIntProperty(wxT("ip_conntrack_tcp_timeout_established"), wxPG_LABEL, std::min(timeouts.stESTABLISHED, def.stESTABLISHED)	) );
	m_pGrid->Append( new wxIntProperty(wxT("ip_conntrack_tcp_timeout_syn_sent"),	wxPG_LABEL, std::min(timeouts.stSYN_SENT, def.stSYN_SENT)		) );
	m_pGrid->Append( new wxIntProperty(wxT("ip_conntrack_tcp_timeout_syn_recv"),	wxPG_LABEL, std::min(timeouts.stSYN_RECV, def.stSYN_RECV)		) );
	m_pGrid->Append( new wxIntProperty(wxT("ip_conntrack_tcp_timeout_fin_wait"),	wxPG_LABEL, std::min(timeouts.stFIN_WAIT, def.stFIN_WAIT)		) );
	m_pGrid->Append( new wxIntProperty(wxT("ip_conntrack_tcp_timeout_time_wait"),	wxPG_LABEL, std::min(timeouts.stTIME_WAIT, def.stTIME_WAIT)		) );
	m_pGrid->Append( new wxIntProperty(wxT("ip_conntrack_tcp_timeout_close"),		wxPG_LABEL, std::min(timeouts.stCLOSE, def.stCLOSE)				) );
	m_pGrid->Append( new wxIntProperty(wxT("ip_conntrack_tcp_timeout_close_wait"),	wxPG_LABEL, std::min(timeouts.stCLOSE_WAIT, def.stCLOSE_WAIT)	) );
	m_pGrid->Append( new wxIntProperty(wxT("ip_conntrack_tcp_timeout_last_ack"),	wxPG_LABEL, std::min(timeouts.stLAST_ACK, def.stLAST_ACK)		) );
	
	m_pGrid->Append( new wxIntProperty(wxT("ip_conntrack_tcp_be_liberal"),			wxPG_LABEL, 1) );
	m_pGrid->Append( new wxIntProperty(wxT("ip_conntrack_icmp_timeout"),			wxPG_LABEL, 10) );
	m_pGrid->Append( new wxIntProperty(wxT("ip_conntrack_udp_timeout"),				wxPG_LABEL, std::min(timeouts.stUDP, def.stUDP)					) );
	m_pGrid->Append( new wxIntProperty(wxT("ip_conntrack_udp_timeout_stream"),		wxPG_LABEL, std::min(timeouts.stUDPStream, def.stUDPStream)		) );
	m_pGrid->Append( new wxIntProperty(wxT("ip_conntrack_max"),						wxPG_LABEL, timeouts.stMaxEntries) );

	m_pGrid->Append( new wxPropertyCategory(wxT("TCP")) );

	m_pGrid->Append( new wxIntProperty(wxT("tcp_fin_timeout"),						wxPG_LABEL, 15) );
	m_pGrid->Append( new wxIntProperty(wxT("tcp_keepalive_time"),					wxPG_LABEL, 1800) );
	m_pGrid->Append( new wxIntProperty(wxT("tcp_keepalive_intvl"),					wxPG_LABEL, 180) );
	m_pGrid->Append( new wxIntProperty(wxT("tcp_keepalive_probes"),					wxPG_LABEL, 2) );
	m_pGrid->Append( new wxIntProperty(wxT("tcp_orphan_retries"),					wxPG_LABEL, 1) );
	m_pGrid->Append( new wxIntProperty(wxT("tcp_syncookies"),						wxPG_LABEL, 1) );
	m_pGrid->Append( new wxIntProperty(wxT("tcp_synack_retries"),					wxPG_LABEL, 4) );
	m_pGrid->Append( new wxIntProperty(wxT("tcp_syn_retries"),						wxPG_LABEL, 4) );
	m_pGrid->Append( new wxIntProperty(wxT("tcp_window_scaling"),					wxPG_LABEL, 1) );
	m_pGrid->Append( new wxIntProperty(wxT("tcp_tw_reuse"),							wxPG_LABEL, 0) );
	m_pGrid->Append( new wxIntProperty(wxT("tcp_sack"),								wxPG_LABEL, 1) );
	m_pGrid->Append( new wxIntProperty(wxT("tcp_timestamps"),						wxPG_LABEL, 0) );
	m_pGrid->Append( new wxIntProperty(wxT("tcp_ecn"),								wxPG_LABEL, 1) );
	m_pGrid->Append( new wxIntProperty(wxT("tcp_fack"),								wxPG_LABEL, 1) );
	m_pGrid->Append( new wxIntProperty(wxT("tcp_rfc1337 "),							wxPG_LABEL, 1) );


	m_pGrid->Append( new wxPropertyCategory(wxT("ICMP")) );
	m_pGrid->Append( new wxIntProperty(wxT("icmp_echo_ignore_broadcasts"),			wxPG_LABEL, 1) );
	m_pGrid->Append( new wxIntProperty(wxT("icmp_ignore_bogus_error_responses"),	wxPG_LABEL, 1) );
}

CAdvancedOptDlg::~CAdvancedOptDlg(void)
{
}

void CAdvancedOptDlg::OnClose(wxCloseEvent& event)
{

}

void CAdvancedOptDlg::OnDefault(wxCommandEvent& ev)
{
	CreateGrid();
}

STRINGPAIRLIST CAdvancedOptDlg::Save()
{
	STRINGPAIRLIST lst;

	wxPropertyGridConstIterator it;

    for ( it = m_pGrid->GetIterator();
          !it.AtEnd();
          it++ )
    {
        const wxPGProperty* p = *it;

        STRINGPAIR pair;

		pair.strVal   = p->GetValueAsString();
		pair.strLabel = p->GetLabel();

		lst.push_back(pair);
    }

	return lst;
}

void CAdvancedOptDlg::Load(const STRINGPAIRLIST& lst)
{
	for ( STRINGPAIRLIST::const_iterator iCur=lst.begin();iCur!=lst.end();iCur++ )
	{
		const STRINGPAIR& pair = *iCur;

		wxPropertyGridIterator it;

		for ( it = m_pGrid->GetIterator();
				  !it.AtEnd();
				  it++ )
		{
			wxPGProperty* p = *it;
			wxString strVal   = p->GetValueAsString();

			if ( pair.strLabel==p->GetLabel() &&
				 pair.strVal!=p->GetValueAsString() )
			{
				p->SetValueFromString( pair.strVal );
				p->SetWasModified();
				break;
			}
		}
	}
}
